Android c++层 Handler分析和使用

您所在的位置:网站首页 bbox looper怎么用 Android c++层 Handler分析和使用

Android c++层 Handler分析和使用

2024-07-12 20:01| 来源: 网络整理| 查看: 265

文章目录 1. C++层的Looper分析1. C++层的Handler: MessageHandler2. C++ Messagehandler的使用3. Looper::sendMessage 流程4. addFd函数5. 代码使用案例1. MessageHandler2. FD监听 2. 总结:

1. C++层的Looper分析

文件:

platform/system/core/include/utils/Looper.h platform/system/core/libutils/Looper.cpp

前面的文章 Android Looper与Message 中最后 可以看到,Java层的MessageQueue的等待/唤醒机制其实是由底层的Looper 中对epoll进行操作来实现的。其实在同一个逻辑流程中, 也对C++层的Message做了通知处理。 (C++中的Looper对Java层MessageQueue的影响就只有等待唤醒机制,没有其他的逻辑影响) 1. C++层的Handler: MessageHandler MessageHandler //system/core/include/utils/Looper.h /** * Interface for a Looper message handler. * * The Looper holds a strong reference to the message handler whenever it has * a message to deliver to it. Make sure to call Looper::removeMessages * to remove any pending messages destined for the handler so that the handler * can be destroyed. */ class MessageHandler : public virtual RefBase { protected: virtual ~MessageHandler() { } public: /** * Handles a message. */ virtual void handleMessage(const Message& message) = 0; }; Message /** * A message that can be posted to a Looper. */ struct Message { Message() : what(0) { } Message(int what) : what(what) { } /* The message type. (interpretation is left up to the handler) */ int what; }; 2. C++ Messagehandler的使用

Messagehandler在使用上其实也很简单:

//1. 导入Looper.h #include //2. 获取当前线程的Looper对象: sp looper = Looper::getForThread(); //3. 发送Message到当前线程的Looper队列中,等待回调: mHandler = new MHandler(); msg = new Message(1/*what*/); looper ->sendMessage(delay, mHandler/*MessageHandler*/, msg/*Message*/); //------------------------------------------------------- //mHandler class MHandler: public MessageHandler { public: virtual void handleMessage(const Message& message) override; } void MHandler::handleMessage(const Message& message) { //最后会调用到这里 } 3. Looper::sendMessage 流程 将事件封装入队 void Looper::sendMessage(const sp& handler, const Message& message) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); sendMessageAtTime(now, handler, message); } void Looper::sendMessageAtTime(nsecs_t uptime, const sp& handler, const Message& message) { #if DEBUG_CALLBACKS ALOGD("%p ~ sendMessageAtTime - uptime=%" PRId64 ", handler=%p, what=%d", this, uptime, handler.get(), message.what); #endif size_t i = 0; { // acquire lock AutoMutex _l(mLock); size_t messageCount = mMessageEnvelopes.size(); while (i = mMessageEnvelopes.itemAt(i).uptime) { i += 1; //按照嗲用时间进行排序,计算要插入的位置 } //将Handler和Message封装成MessageEnvelope对象, 然后插入到mMessageEnvelopes队列中; MessageEnvelope messageEnvelope(uptime, handler, message); mMessageEnvelopes.insertAt(messageEnvelope, i, 1); // Optimization: If the Looper is currently sending a message, then we can skip // the call to wake() because the next thing the Looper will do after processing // messages is to decide when the next wakeup time should be. In fact, it does // not even matter whether this code is running on the Looper thread. if (mSendingMessage) { return; } } // release lock // Wake the poll loop only when we enqueue a new message at the head. if (i == 0) { wake(); } } pollOnce之后,进行对Handler和Message的处理: int Looper::pollInner(int timeoutMillis) { ... //-----------------1. 对Java层MQ阻塞事件和addFd函数添加的fd中的事件进行处理--------------------------------------------------------- for (int i = 0; i = 0) { int events = 0; if (epollEvents & EPOLLIN) events |= EVENT_INPUT; if (epollEvents & EPOLLOUT) events |= EVENT_OUTPUT; if (epollEvents & EPOLLERR) events |= EVENT_ERROR; if (epollEvents & EPOLLHUP) events |= EVENT_HANGUP; pushResponse(events, mRequests.valueAt(requestIndex)); //添加Request的Response事件 } else { ALOGW("Ignoring unexpected epoll events 0x%x on fd %d that is " "no longer registered.", epollEvents, fd); } } } Done: ; //----------------------2. 对C++层Handler(MessageHandler)事件进行处理----------------------------------------------- // Invoke pending message callbacks. mNextMessageUptime = LLONG_MAX; while (mMessageEnvelopes.size() != 0) { nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); const MessageEnvelope& messageEnvelope = mMessageEnvelopes.itemAt(0);//取出队列中的MessageEnvelope if (messageEnvelope.uptime handleMessage(message); } // release handler mLock.lock(); mSendingMessage = false; result = POLL_CALLBACK; } else { // The last message left at the head of the queue determines the next wakeup time. mNextMessageUptime = messageEnvelope.uptime; break; } } } // Release lock. mLock.unlock(); //--------------------------3. 对addFd函数中request注册的回调进行处理(Response事件处理)--------------------------------------------------- // Invoke all response callbacks. for (size_t i = 0; i handleEvent(fd, events, data); if (callbackResult == 0) { removeFd(fd, response.request.seq); } //清除CallBack response.request.callback.clear(); result = POLL_CALLBACK; } } 4. addFd函数

addFd函数,在调用时, 传入一个需要添加的fd到对应Looper的epoll事件监听池中,对fd中感兴趣的事件进行监听,监听的结果会返回到传入的监听器中,见上面代码中分析的第三点;

addFd时需要传入的CallBack监听器: ///system/core/include/utils/Looper.h /** * A looper callback. */ class LooperCallback : public virtual RefBase { protected: virtual ~LooperCallback() { } public: /** * Handles a poll event for the given file descriptor. * It is given the file descriptor it is associated with, * a bitmask of the poll events that were triggered (typically EVENT_INPUT), * and the data pointer that was originally supplied. * * Implementations should return 1 to continue receiving callbacks, or 0 * to have this file descriptor and callback unregistered from the looper. */ virtual int handleEvent(int fd, int events, void* data) = 0; }; SimpleLooperCallback

SimpleLooperCallback 时对LooperCallback的简单封装, 目的主要是为了addFd的一个重载,用于函数式调用

/** * Wraps a Looper_callbackFunc function pointer. */ class SimpleLooperCallback : public LooperCallback { protected: virtual ~SimpleLooperCallback(); public: SimpleLooperCallback(Looper_callbackFunc callback); virtual int handleEvent(int fd, int events, void* data); private: Looper_callbackFunc mCallback; }; addFd函数: int Looper::addFd(int fd, int ident, int events, Looper_callbackFunc callback, void* data) { return addFd(fd, ident, events, callback ? new SimpleLooperCallback(callback) : NULL, data); //SimpleLooperCallback即用于该重载, 为了简单化callBack的传入类型, 之间穿入一个函数指针; } //最终调用的这一个addFd int Looper::addFd(int fd, int ident, int events, const sp& callback, void* data) { if (!callback.get()) { if (! mAllowNonCallbacks) { ALOGE("Invalid attempt to set NULL callback but not allowed for this looper."); return -1; } if (ident wake(); } break; } if (looper) { looper->sendMessage(handler, Message(1)); sleep(1); } } } 2. FD监听 #include "looper/Looper.h" #include #include #include using namespace android; static bool isQuit = false; int main() { int fds[2]; // int ret = pipe(fds); // if (ret == -1) { // strerror(errno); // exit(1); // } int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, fds); if (ret == -1) { strerror(errno); exit(1); } pid_t pid = fork(); if (pid == 0) { //子进程, 关闭write fd, 监听receive fd close(fds[0]); //创建looper std::shared_ptr looper = Looper::getForThread(); if (looper == nullptr) { looper = Looper::prepare(0); } //创建FD监听的looper callback class MyCallback : public LooperCallback { int handleEvent(int fd, int events, void* data) { printf("[%d]handleEvent, fd=%d\n", getpid(), fd); if (events & Looper::EVENT_INPUT) { printf("[%d]EVENT_INPUT\n", getpid()); //读取内容...... char buf[256]; ::recv(fd, buf, 256, 0); //read(fd, buf, 256); printf("[%d]receive: %s\n", getpid(), buf); if (strncmp("exit", buf, 4) == 0) { printf("[%d]EXIT!!!\n", getpid()); isQuit = true; } } else if (events & Looper::EVENT_OUTPUT) { printf("[%d]EVENT_OUTPUT\n", getpid()); } else if (events & Looper::EVENT_ERROR) { printf("[%d]EVENT_ERROR\n", getpid()); } else if (events & Looper::EVENT_HANGUP) { printf("[%d]EVENT_HANGUP\n", getpid()); } else { printf("[%d]else....\n", getpid()); } } }; //监听read fd auto callback = std::make_shared(); looper->addFd(fds[1], Looper::POLL_CALLBACK, Looper::EVENT_INPUT/*|Looper::EVENT_OUTPUT*/, callback, NULL); //loop while (!isQuit){ printf("[%d]pollOnce\n", getpid()); looper->pollOnce(-1); printf("pollOnce 222\n"); } close(fds[1]); } else if (pid > 0){ //主进程, 关闭read fd close(fds[1]); int count = 0; while (true) { if (isQuit) { break; } const char *buf = std::to_string(count++).c_str(); //printf("[%d]: fd= %d, Send: %s\n", getpid(), fds[0], buf); ::send(fds[0], buf, 10, 0); //write(fds[0], buf, 10); usleep(10); if (count >= 10000) { printf("[%d]: wait....\n", getpid()); char exitBuf[6] = "exit\n"; ::send(fds[0], exitBuf, 10, 0); //sleep(100); isQuit = true; } } close(fds[0]); } } 2. 总结: 逻辑相关: Looper中的事件队列机制, 集成了两种事件处理监听机制: addFd: 对添加的文件描述符中的(写入/写出)事件仅从监听处理;MessageHandler: C++层的Handler机制;

2.非逻辑相关:

Looper中的mWakeEventFd只是对Java层MQ的阻塞/唤醒机制做控制,而不影响Java MQ的逻辑。Java MQ只是借助了该Looper进行阻塞实现。Looper中的mWakeEventFd只是对Java层MQ的阻塞/唤醒机制做控制,而不影响- - – Java MQ的逻辑。Java MQ只是借助了该Looper进行阻塞实现。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3